<template>
    <div class="qilin-QilinForm"
        :style="ownFormConfig?.elFormConfig?.style"
    >
        <el-form
            ref="formData"
            :key="componentKey"
            :model="ownFormConfig.submitData"
            :rules="ownFormRules"
            :label-position="ownFormConfig?.elFormConfig?.labelPosition || 'right' "
            :label-width="ownFormConfig?.elFormConfig?.labelWidth || '60px' "
            :label-suffix="ownFormConfig?.elFormConfig?.labelSuffix || ':' "
            :size="ownFormConfig?.elFormConfig?.size || 'default' "
            :class="ownFormConfig?.elFormConfig?.className"
        >
            <template v-for="(item,index) in ownFormConfig.itemConfig" :key="item.dataName || 'form-key-'+index ">
                <el-form-item
                    v-if="!item.isHide"
                    :label="item.labelName || (!item.hideLabel ? '默认名称'+index : '' ) "
                    :prop="item.dataName"
                    :style="item.itemStyle"
                    :class="[
                        'width'+(item.width ? item.width : 24 ),
                        item.className
                    ]"
                >
                    <template v-if="item.type === 'input' || !item.type ">
                        <el-input
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :type="item.inputType || 'text' "
                            :clearable="item.clearable ?? true "
                            :disabled="item.disabled || false "
                            :placeholder="item.placeholder || '请输入'+item.labelName "
                            :show-password="item.showPassword || false "
                            :rows="item.rows || 2"
                            :autocomplete="item.inputType === 'password' ? 'new-password' : 'new-text' "
                            :prefix-icon="item.prefixIcon"
                            :suffix-icon="item.suffixIcon"
                            v-number:[item]="item.number"
                            :style="item.style"
                            :maxlength="item.maxlength ? item.maxlength : '' "
                            :minlength="item.minlength ? item.minlength : '' "
                            :show-word-limit="['text','textarea'].includes(item.inputType)"
                            @input="(val)=>{
                                synchronous('input',item,val);
                            }"
                            @blur="(val)=>{
                                synchronous('blur',item,val);
                            }"
                        >
                            <template v-slot:prefix>
                                <slot :name="item.prefixSlotName" :data="{data:ownFormConfig.submitData[item.dataName],item}"></slot>
                            </template>
                            <template v-slot:suffix>
                                <slot :name="item.suffixSlotName" :data="{data:ownFormConfig.submitData[item.dataName],item}"></slot>
                            </template>
                        </el-input>
                    </template>
                    <template v-else-if="item.type === 'number' ">
                        <el-input-number
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :disabled="item.disabled || false"
                            :max="item.max || Infinity"
                            :min="item.min ?? -Infinity"
                            :controls-position="item.controlsPosition || ''"
                        ></el-input-number>
                    </template>
                    <template v-else-if="item.type === 'select' ">
                        <el-select
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :clearable="item.clearable ?? true "
                            :disabled="item.disabled || false "
                            :placeholder="item.placeholder || '请选择'+item.labelName "
                            :multiple="item.multiple || false "
                            :collapse-tags="item.collapseTags || false "
                            :filterable="item.filterable ?? true "
                            :remote="item.remote ?? false"
                            :remote-method="item.remoteMethod"
                            :loading="item.loading ?? false"
                            :style="item.style"
                            @blur="(event)=>{
                                synchronous('blur',item,event)
                            }"
                            @change="(val)=>{
                                synchronous('change',item,val)
                            }"
                        >
                            <el-option
                                v-for="optItem in ownFormConfig.selectLists[item.dataListName]"
                                :key="optItem.value ?? optItem[item.selectOptionValueName] "
                                :disabled="optItem.disabled || false "
                                :label="optItem.label ?? optItem[item.selectOptionLableName] "
                                :value="optItem.value ?? optItem[item.selectOptionValueName] "
                            ></el-option>
                        </el-select>
                    </template>
                    <template v-else-if="item.type === 'cascader' ">
                        <el-cascader
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :placeholder="item.placeholder || '请选择'+item.labelName "
                            :options="ownFormConfig.selectLists[item.dataListName] || [] "
                            :props="item.cascaderProps"
                            :disabled="item.disabled || false "
                            ref="cascaderRef"
                            @change="(val)=>{
                                synchronous('change',item,val,cascaderRef)
                            }"
                        ></el-cascader>
                    </template>
                    <template v-else-if="item.type === 'radio' ">
                        <el-radio-group
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :disabled="item.disabled || false "
                            @change="(val)=>{item.change && item.change(val,item)}"
                        >
                            <el-radio
                                v-for="item1 in ownFormConfig.selectLists[item.dataListName]"
                                :label="item1.value"
                                :name="item1.value+'' "
                                :key="item1.label"
                                :disabled="item1.disabled || false "
                                v-show="!item1.isHide"
                            >{{item1.label}}</el-radio>
                        </el-radio-group>
                    </template>
                    <template v-else-if="item.type === 'switch' ">
                        <el-switch
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :disabled="item.disabled || false "
                            :size="item.size || 'default' "
                            :active-text="item.activeText || '' "
                            :inactive-text="item.inactiveText || '' "
                            :active-value="item.activeValue || '' "
                            :inactive-value="item.inactiveValue || '' "
                        ></el-switch>
                    </template>
                    <template v-else-if="item.type === 'date' ">
                        <el-date-picker
                            v-model="ownFormConfig.submitData[item.dataName]"
                            :type="item.dateType || 'date' "
                            :disabled="item.disabled || false "
                            :placeholder="
                                !item.dateType.includes('range') ? (item.placeholder || '请选择'+item.labelName) : ''
                            "
                            :start-placeholder="
                                item.dateType.includes('range') ? item.startPlaceholder || '开始时间' : ''
                            "
                            :end-placeholder="
                                item.dateType.includes('range') ? item.endPlaceholder || '结束时间' : ''
                            "
                            :format="item.format || 'YYYY-MM-DD HH:mm:ss' "
                            :value-format="item.valueFormat || 'YYYY-MM-DD HH:mm:ss' "
                            :default-time="
                                item.defaultTime ||
                                (item.dateType.includes('range') ? [new Date(2000,1,1,8,30,0),new Date(2000,1,1,17,30,0)] : new Date(2000,1,1,8,30,0))
                            "
                            :style="`width:${item.domWidth ? item.domWidth+'px' : '100%'};`"
                            @blur="(event)=>{
                                synchronous('blur',item,event)
                            }"
                            @change="(val)=>{
                                synchronous('change',item,val)
                            }"
                        ></el-date-picker>
                    </template>
                    <template v-else-if="item.type === 'upload' ">
                        <QilinUploadFile
                            v-model:uploadFileConfig="ownFormConfig.itemConfig[index]"
                            @success="(fileList)=>{
                                ownFormConfig.submitData[item.dataName]=fileList
                            }"
                        ></QilinUploadFile>
                    </template>
                    <template v-else-if="item.type === 'image' ">
                        <QilinUploadImage
                            v-model:uploadImageConfig="ownFormConfig.itemConfig[index]"
                            :fileList="ownFormConfig.submitData[item.dataName]"
                            @success="(fileList)=>{
                                ownFormConfig.submitData[item.dataName]=fileList;
                                formClearValidate(item.dataName);
                            }"
                        ></QilinUploadImage>
                    </template>
                    <template v-else-if="item.type === 'checkbox' ">
                        <el-checkbox-group
                            v-model="ownFormConfig.submitData[item.dataName]"
                            @change="(event)=>{
                                synchronous('change',item,event);
                            }"
                        >
                            <el-checkbox
                                v-for="ite in ownFormConfig.selectLists[item.dataListName]"
                                :key="ite.label"
                                :label="ite.label"
                                :disabled="ite.disabled || false "
                            ></el-checkbox>
                        </el-checkbox-group>
                    </template>
                    <template v-else-if="item.type === 'richtext' ">
                        <QilinRichtext
                            ref="QilinRichtextRef"
                        ></QilinRichtext>
                    </template>
                    <template v-else-if="item.type === 'quillRichtext' ">
                        <QilinQuillRichtext
                            ref="QilinQuillRichtextRef"
                            v-model:quillRichtextConfig="item.richtextConfig"
                            :content="ownFormConfig.submitData[item.dataName]"
                            @success="(value)=>{
                                ownFormConfig.submitData[item.dataName]=value;
                            }"
                        ></QilinQuillRichtext>
                    </template>
                    <template v-else-if="item.type === 'wangRichtext' ">
                        <QilinWangEditorRichtext
                            ref="QilinWangEditorRichtextRef"
                            v-model:wangConfig="item.wangConfig"
                            :content="ownFormConfig.submitData[item.dataName]"
                            @success="(value)=>{
                                if(value !== '<p><br></p>'){
                                    ownFormConfig.submitData[item.dataName]=value;
                                    formClearValidate(item.dataName);
                                }
                            }"
                        ></QilinWangEditorRichtext>
                    </template>
                    <template v-else-if="item.type === 'slot' ">
                        <slot
                            :name="item.slotName"
                            :data="{item}"
                        ></slot>
                    </template>
                </el-form-item>
            </template>
            <slot name="extraFormItem"></slot>
            <el-form-item
                :class="['qilin-QilinForm-button',ownFormConfig.buttonConfigClassName]"
                v-if="ownFormConfig.buttonConfig && ownFormConfig.buttonConfig.length > 0 "
            >
                <template v-for="(item,index) in ownFormConfig.buttonConfig" :key="'button-'+index">
                    <el-button
                        :type="item.type || 'primary' "
                        :size="item.size || 'default' "
                        :class="item.className"
                        @click="item.click && item.click(item.formRefName,$event) "
                        v-bind="item"
                    >{{item.btnName || "按钮"}}</el-button>
                </template>
            </el-form-item>
        </el-form>
        <slot name="extraItem"></slot>
    </div>
</template>

<script setup>
import Qilin from "qilin-utils";
import QilinFormRules from "./formRule.js";
import QilinUploadFile from "../QilinUploadFile/QilinUploadFile.vue";
import QilinWangEditorRichtext from "../QilinRichtext/QilinWangEditorRichtext.vue";

/*
    数据变量定义区域
*/
// 组件自身的校验规则
let ownFormRules=reactive({});
let componentKey=ref(0);
// 获取当前表单元素DOM
const formData=ref(null);
const QilinQuillRichtextRef=ref(null);
const QilinWangEditorRichtextRef=ref(null);
const QilinRichtextRef=ref(null);
const cascaderRef=ref(null);


/*
    计算属性等代码区域
*/
// 接收父组件传来的值--父组件定义的配置项建议放在脚本逻辑最下方
const propsValue=defineProps({
    formConfig:{
        type:Object,
        default(){
            return {
                // el-form标签上的相关配置
                elFormConfig:{
                    labelPosition:"right", //label对齐方式--默认right
                    labelWidth:"60px", //label宽度--默认60px
                    labelSuffix:":", //label后缀--默认：
                    size:"default", //el-form的大小--默认default
                    className:"", //el-form的自定义类名
                    style:"", //最外层元素的自定义行内样式
                },
                // 表单结构相关配置项
                itemConfig:[
                    {
                        dataName:"name", //对应后台数据名
                        labelName:"姓名", //label名称
                        hideLabel:false, //是否隐藏label字段
                        type:"input", //表单组件类型--默认为input
                        dateType:"date", //时间选择器类型--默认为date--当type为date时生效
                        format:"YYYY-MM-DD HH:mm:ss", //时间格式化配置--默认YYYY-MM-DD HH:mm:ss--当type为date时生效
                        valueFormat:"YYYY-MM-DD HH:mm:ss", //时间格式化配置--默认YYYY-MM-DD HH:mm:ss--当type为date时生效
                        startPlaceholder:"", //日期开始提示语--当type为date时生效
                        endPlaceholder:"", //日期结束提示语--当type为date时生效
                        dataListName:"", //下拉数据名对应selectLists中属性--当type为select时生效
                        inputType:"text", //表单input类型--默认为text--仅当type为input时生效
                        number:"", //当输入框为数字输入框时，允许输入的整数位数
                        decimal:"", //当输入框为数字输入框时，允许输入的小数位数
                        prefixIcon:"", //输入框前置内置图标
                        prefixSlotName:"", //输入框前置内置图标插槽名称
                        suffixIcon:"", //输入框后置内置图标
                        suffixSlotName:"", //输入框后置内置图标插槽名称
                        selectOptionValueName:"value", //下拉选项中的value对应的字段名，默认为value
                        selectOptionLabelName:"label", //下拉选项中的label对应的字段名，默认为label
                        width:24, //表单item的栅栏占比宽度--默认24
                        className:"", //el-form-item的自定义类名
                        clearable:true, //是否可以一键清空--默认true
                        disabled:false, //是否禁用--默认false
                        placeholder:"", //表单提示语
                        showPassword:false, //是否显示密码--默认false--当inputType为password生效
                        rows:2, //行高--默认2--当inputType为textarea生效
                        multiple:false, //是否可以多选--默认false
                        collapseTags:false, //多选时是否将选中值按文字的形式展示--默认false--当type为select时生效
                        filterable:true, //是否可搜索--默认true--当type为select时生效
                        cascaderProps:{ //配置级联选择的配置项--当type为cascader时生效
                            expandTrigger:"click", //次级菜单的展开方式，click、hover
                            multiple:false, //是否多选
                            checkStrictly:false, //是否严格的遵守父子节点不互相关联
                            emitPath:true, //在选中节点改变时，是否返回由该节点所在的各级菜单的值所组成的数组，若设置false，则只返回该节点的值
                            lazy:false, //是否动态加载子节点，需与lazyLoad方法结合使用
                            lazyLoad:"event", //加载动态数据的方法，仅在lazy为true时生效
                            value:"value", //指定选项的值为选项对象的某个属性值
                            label:"label", //指定选项标签为选项对象的某个属性值
                            children:"children", //指定选项的子选项为选项对象的某个属性值
                            disabled:"disabled", //指定选项的禁用为选项对象的某个属性值
                            leaf:"leaf", //指定选项的叶子节点的标志为选项对象的某个属性值
                            hoverThreshold:500 //hover时展开菜单的灵敏度阈值
                        },
                        slotName:"", //slot具名插槽名称
                        maxlength:"", //最大输入长度
                        minlength:"", //最小输入长度
                        max:"", //最大输入数字
                        min:"", //最小输入数字
                        controlsPosition:"", //数字输入框的控制按钮位置
                        size:"default", //switch的大小，默认default
                        activeText:"", //switch打开时的文字描述
                        inactiveText:"", //switch关闭时的文字描述
                        activeValue:"", //switch状态为on时的值
                        inactiveValue:"", //switch状态为off时的值
                        style:"", //额外行内样式
                        itemStyle:"", //额外的el-form-item的样式
                        loadMore:"event", //下拉滚动加载事件--当type为select时生效
                        change:"event", //change事件
                        clear:"event", //clear事件
                        loading:false,
                        remote:false,
                        autocomplete:"off", //点击密码框是否提示快捷密码，默认off不提示
                        defaultTime:new Date(2000,1,1,8,30,0), // 当选择时间时默认选中的时分秒时刻，默认8点半
                        domWidth:220, //元素的长度，默认为220px
                    }
                ],
                // 下拉数据集
                selectLists:{},
                // 提交到后台的数据集
                submitData:{},
                // 表单底部操作提交按钮相关配置项
                buttonConfig:[
                    // {
                    //     btnName:"按钮", //按钮名称
                    //     type:"primary", //按钮类型
                    //     size:"default", //按钮大小
                    //     className:"", //按钮自定义类名
                    //     formRefName:"", //表单元素DOM
                    //     click:"event" //点击事件
                    // }
                ],
                buttonConfigClassName:"" //表单底部按钮自定义类名
            };
        }
    }
});

// 暴露父组件自定义方法
const emits=defineEmits(["update:formConfig","synchronous"]);

// 组件自身的配置项
let ownFormConfig=computed({
    get(){
        return propsValue.formConfig;
    },
    set(val){
        emits("update:formConfig",val);
    }
});


/*
    逻辑脚本代码区域
*/
// 创建表单的校验规则
const createFormRules=()=>{
    let ruleObj={};
    ownFormConfig.value.itemConfig.forEach((item)=>{
        if(item.validate && item.validate.length > 0){
            ruleObj[item.dataName]=item.validate;
        };
        if(item.otherValidate){
            if(ruleObj[item.dataName] && ruleObj[item.dataName].length > 0){
                ruleObj[item.dataName]=ruleObj[item.dataName].concat(QilinFormRules[item.otherValidate]);
            }else{
                ruleObj[item.dataName]=QilinFormRules[item.otherValidate];
            };
        };
    });
    ownFormRules=ruleObj;
    componentKey.value += 1;
};

// 触发表单元素定义事件
const synchronous=(eventType,item,e,ref)=>{
    // console.log(eventType,item,e);
    if(item.type === "cascader"){
        // console.log(ref[0].getCheckedNodes()[0]);
        formValidateField(item.dataName);
        item[eventType] && item[eventType](item,e,ref[0].getCheckedNodes()[0]);
    }else{
        item[eventType] && item[eventType](item,e);
    };
};

// 调用el-form表单组件的校验事件监听
const formValidate=(callback)=>{
    // console.log(QilinQuillRichtextRef.value);
    ownFormConfig.value.itemConfig.forEach((item)=>{
        if(item.type === "quillRichtext"){ //若输入完富文本后直接点击提交按钮，须手动触发一次失去焦点事件
            // QilinQuillRichtextRef.value[0].handleBlur();
            QilinQuillRichtextRef.value.forEach((ite)=>{
                ite.handleBlur();
            });
        };
        if(item.type === "wangRichtext"){ //若输入完富文本后直接点击提交按钮，须手动触发一次失去焦点事件
            // console.log(QilinWangEditorRichtextRef.value)
            QilinWangEditorRichtextRef.value.forEach((ite)=>{
                ite.handleBlur();
            });
        };
    });
    formData.value.validate((valid)=>{
        if(callback){
            callback(valid);
        };
    });
};
// 调用el-form表单组件的单字段校验事件监听
const formValidateField=(dataName,callback)=>{
    formData.value.validateField(dataName,(valid)=>{
        if(callback){
            callback(valid);
        };
    });
};
// 调用el-form表单组件的清空校验事件监听
const formResetFields=()=>{
    nextTick(()=>{
        formData.value.resetFields();
        // for(let key in ownFormConfig.value.submitData){
        //     ownFormConfig.value.submitData[key]="";
        // };
        ownFormConfig.value.itemConfig.forEach((item)=>{
            if(item.type === "image"){
                item.fileList=[];
                ownFormConfig.value.submitData[item.dataName]=[];
            }else if(item.type === "number"){
                ownFormConfig.value.submitData[item.dataName]=item.min;
            }else if(item.type === "checkbox"){
                ownFormConfig.value.submitData[item.dataName]=[];
            }else{
                ownFormConfig.value.submitData[item.dataName]="";
            };
        });
    });
};
// 调用el-form表单组件的单字段清除校验事件监听
const formClearValidate=(dataName)=>{
    formData.value.clearValidate(dataName);
};


/*
    生命周期等代码区域
*/
createFormRules();
// 暴露子组件的方法
defineExpose({
    formValidate,
    formResetFields,
    formClearValidate,
    formValidateField,
    createFormRules
});

</script>

<style lang="scss" scoped>
.qilin-QilinForm{
    width:100%;
    >.el-form{
        overflow:hidden;
        >.el-form-item{
            float:left;
        }
        >.width24{
            width:100%;
        }
        >.width18{
            width:75%;
        }
        >.width16{
            width:66.66%;
        }
        >.width12{
            width:50%;
        }
        >.width8{
            width:33.33%;
        }
        >.width6{
            width:25%;
        }
        >.el-form-item.qilin-QilinForm-button{
            width:100%;
            :deep(>.el-form-item__content){
                // margin-left:0!important;
                text-align:center;
            }
        }
        .el-select{
            width:100%;
        }
    }
}
</style>
